//
//  EWEBluetooth.swift
//  Auscultation
//
//  Created by 来 on 2020/11/30.
//

import Foundation
import CoreBluetooth

class EWEBluetooth: NSObject {
    
    var manager: CBCentralManager!
    var pmanager: CBPeripheralManager!
    var peripherals: [CBPeripheral] = []
    var selectPeripheral: CBPeripheral?
    var writeCharacteristic: CBCharacteristic?
    var readCharacteristic: CBCharacteristic?
    var cCharacteristic: CBCharacteristic?
    var isOffLine: Bool = true
    
    /// 单例
    public static let lgf = EWEBluetooth()
    private override init() { }
    
    // 初始化蓝牙中心
    func initBluetooth() {
        if manager == nil {
            manager = CBCentralManager.init(delegate: self, queue: nil, options: [
                                                "CBCentralManagerOptionShowPowerAlertKey": true,
                                                "CBCentralManagerOptionRestoreIdentifierKey": "EWEBluetooth"])
        }
    }
    
    // 开始扫描
    func startScan() {
        if manager.state == .poweredOn {
            finishScan()
            SVProgressHUD.show()
            Timer.lgf_After(S: 0.5) {
                self.manager.scanForPeripherals(withServices: [CBUUID.init(string: "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"), CBUUID.init(string: "FE59")], options: nil)
            }
        } else {
            debugPrint("蓝牙未开启")
            SVProgressHUD.showError("请开启蓝牙")
        }
    }
    
    // 结束扫描
    func stopScan() {
        SVProgressHUD.dismiss()
        if manager.isScanning {
            manager.stopScan()
        }
    }
    
    // 释放设备蓝牙
    func finishScan() {
        SVProgressHUD.dismiss()
        manager.stopScan()
        selectPeripheral = nil
        peripherals.forEach { (peripheral) in
            manager.cancelPeripheralConnection(peripheral)
        }
        peripherals.removeAll()
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "FINISH_SCAN"), object: nil)
    }
    
    // 连接设备
    func connection(_ peripheral: CBPeripheral) {
        if manager == nil {
            return
        }
        SVProgressHUD.show()
        manager.connect(peripheral, options: nil)
    }
    
}

extension EWEBluetooth {
    
    func jrtzyd() {
        tctzyd()
        writeValue("a100a100", "进入听诊引导模式")
    }
    
    func tzydxyb() {
        writeValue("b700b700", "听诊引导AI点击")
    }

    func tctzyd() {
        writeValue("a200a200", "退出听诊引导模式")
    }
    
    func hqtzyd() {
        writeValue("a300a300", "获取听诊引导状态")
    }
    
    func tzqy() {
        writeValue("a400a400", "获取听诊区域")
    }
    
    func tzwj() {
        writeValue("a500a500", "获取听诊文件")
    }
    
    func ly() {
        pmhx()
        writeValue("a600a600", "录音（蓝牙同步发送）")
    }
    
    func lys() {
        writeValue("ab00ab00", "录音（保存数据至flash）")
    }
    
    func tzly() {
        writeValue("a700a700", "停止录音保存至原文件")
    }
    
    func tzlyn() {
        writeValue("a800a800", "停止录音保存至新建文件夹")
    }
    
    func qhms() {
        writeValue("a900a900", "切换模式")
    }
    
    func pmhx() {
        writeValue("aa00aa00", "屏幕唤醒")
    }
    
    func tbxt() {
        writeValue("ac00ac00", "同步心跳")
    }
    
    func sbwj() {
        writeValue("b400b400", "设备文件")
    }
    
    func gxsj(_ code: String) {
        writeValue(code, "设备时间更新")
    }
    
    func sbwjwj(_ code: String) {
        writeValue(code, "设备文件文件")
    }
    
    func sbwjwjnr(_ code: String) {
        writeValue(code, "设备文件文件内容")
    }
    
    func jslytb() {
        writeValue("ad00ad00", "结束蓝牙同步")
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "STOP_LU_YIN"), object: nil)
    }
    
    func writeValue(_ ml: String, _ name: String) {
        if manager == nil {
            return
        }
        if selectPeripheral == nil || writeCharacteristic == nil {
            return
        }
        let data: Data = ml.utf8Data()!
        selectPeripheral!.writeValue(data, for: writeCharacteristic!, type: .withoutResponse)
        debugPrint("手机向蓝牙发送指令:\(ml) - \(writeCharacteristic?.uuid.uuidString ?? "") - \(name)")
    }
    
    func readValue(_ ml: String, _ name: String) {
        if manager == nil {
            return
        }
        if selectPeripheral == nil || readCharacteristic == nil {
            return
        }
        let data: Data = ml.utf8Data()!
        selectPeripheral!.writeValue(data, for: readCharacteristic!, type: .withResponse)
        debugPrint("手机向蓝牙发送指令:\(ml) - \(readCharacteristic?.uuid.uuidString ?? "") - \(name)")
    }
}

extension EWEBluetooth: CBPeripheralManagerDelegate {
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        
    }
    
    func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
        debugPrint(central.maximumUpdateValueLength)
        peripheral.setDesiredConnectionLatency(.high, for: central)
    }
    
    func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didUnsubscribeFrom characteristic: CBCharacteristic) {
        
    }
}

extension EWEBluetooth: CBCentralManagerDelegate {
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if manager.state == .poweredOn {
            
        } else {
            debugPrint("蓝牙未开启")
            SVProgressHUD.showError("请开启蓝牙")
        }
    }
    
    
    /// 搜索到新的外设
    ///
    /// - Parameters:
    ///   - central: 蓝牙中心
    ///   - peripheral: 外设
    ///   - advertisementData: 外设广播内容
    ///   - RSSI: 信号
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        if peripheral.name == nil {
            return
        }
        print(peripheral.name ?? "")
        print(peripheral.identifier)
        if !peripherals.contains(peripheral) {
            peripherals.append(peripheral)
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_PERIPHERAL"), object: nil)
            SVProgressHUD.dismiss()
        }
    }
    
    /// 外设断开连接
    ///
    /// - Parameters:
    ///   - central: 蓝牙中心
    ///   - peripheral: 外设
    ///   - error: 错误
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        finishScan()
        isOffLine = true
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ON_OFF_LINE"), object: true)
        debugPrint("外设断开连接")
        debugPrint(error ?? "")
        SVProgressHUD.showError("听诊器断开连接")
    }
    
    /// 连接外设成功
    ///
    /// - Parameters:
    ///   - central: 蓝牙中心
    ///   - peripheral: 外设
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        stopScan()
        selectPeripheral = peripheral
        peripheral.delegate = self
        //搜索外设的所有服务(可指定服务，默认为搜索全部服务)
        peripheral.discoverServices(nil)
        isOffLine = false
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ON_OFF_LINE"), object: false)
        debugPrint("连接外设成功")
        SVProgressHUD.showSuccess("听诊器连接成功")
    }
    
    /// 连接外设失败
    ///
    /// - Parameters:
    ///   - central: 蓝牙中心
    ///   - peripheral: 外设
    ///   - error: 错误
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        finishScan()
        isOffLine = true
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ON_OFF_LINE"), object: true)
        debugPrint("连接外设失败")
        debugPrint(error ?? "")
        if error?.code == 14 {
            let alertVC = UIAlertController.init(title: nil, message: "连接失败，当前设备已恢复出厂，请去手机蓝牙设置忽略 " + (peripheral.name ?? "该设备") + " 的配对，并重新尝试连接", preferredStyle: .alert)
            alertVC.addAction(UIAlertAction.init(title: "确定", style: .default, handler: { (action) in
                if #available(iOS 10.0, *) {
                    if let burl = URL(string: UIApplication.openSettingsURLString) {
                        if UIApplication.shared.canOpenURL(burl) {
                            UIApplication.shared.open(burl, options: [:]) { (success) in }
                        }
                    }
                } else {
                    if let burl = URL(string: "prefs:root=Bluetooth") {
                        if UIApplication.shared.canOpenURL(burl) {
                            UIApplication.shared.openURL(burl)
                         }
                    }
                }
            }))
            alertVC.addAction(UIAlertAction.init(title: "取消", style: .cancel, handler: nil))
            UIApplication.shared.keyWindow?.rootViewController?.present(alertVC, animated: true, completion: nil)
        } else {
            SVProgressHUD.showSuccess("听诊器连接失败")
        }
    }
    
}

extension EWEBluetooth: CBPeripheralDelegate {
    
    
    /// 发现外设的服务
    ///
    /// - Parameters:
    ///   - peripheral: 外设
    ///   - error: 错误
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        if error != nil {
            debugPrint("错误的服务特征===\(error!.localizedDescription)")
        }
        peripheral.services?.forEach {
            //搜索所有的设备特征
            peripheral.discoverCharacteristics(nil, for: $0)
        }
    }
    
    /// 发现外设的服务端的特征
    /// - Parameters:
    ///   - peripheral: 外设
    ///   - service: 服务
    ///   - error: 错误
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        if error != nil {
            print("发现错误的特征：\(error!.localizedDescription)")
            return
        }
        service.characteristics?.forEach({ (characteristic) in
            debugPrint("服务的UUID:\(service.uuid)" + "          " + "特征的UUID:\(characteristic.uuid)")
            if characteristic.uuid.uuidString == "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" {// APP写入
                writeCharacteristic = characteristic
            } else if characteristic.uuid.uuidString == "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" {// 设备返回
                readCharacteristic = characteristic
                peripheral.setNotifyValue(true, for: readCharacteristic!)
            } else if characteristic.uuid.uuidString == "8EC90003-F315-4F60-9FB8-838830DAEA50" {
                cCharacteristic = characteristic
            }
        })
    }
    
    /// 收到外设发送内容
    ///
    /// - Parameters:
    ///   - peripheral: 外设
    ///   - characteristic: 特征
    ///   - error: 错误
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        if error != nil || characteristic.value == nil {
            print("发送数据错误的特性是：\(characteristic.uuid)     错误信息：\(error!.localizedDescription)     错误数据：\(String(describing: characteristic.value))")
            return
        }
        if characteristic.uuid.uuidString == "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" {
            debugPrint("设备返回到的数据 \(characteristic.uuid.uuidString): \(characteristic.value!.hexString())")
        } else if characteristic.uuid.uuidString == "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" {
            let str = characteristic.value!.hexString()
            if str.hasPrefix("A6") {
                if str.count > 10 {
                    let start = str.index(str.startIndex, offsetBy: 12)
                    let end = str.index(str.endIndex, offsetBy: -4)
                    let newStr = str[start..<end]
                    let dataOut = EWEFilter.filter_HT(String(newStr))
                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_DEVICE_DATA_A6_F"), object: dataOut)
                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_DEVICE_DATA_A6"), object: newStr)
                }
            } else if str.hasPrefix("B7") {
                if str.count > 10 {
                    let start = str.index(str.startIndex, offsetBy: 12)
                    let end = str.index(str.endIndex, offsetBy: -4)
                    let newStr = str[start..<end]
                    let dataOut = EWEFilter.filter_HT(String(newStr))
                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_DEVICE_DATA_B7_F"), object: dataOut)
                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_DEVICE_DATA_B7"), object: newStr)
                }
            } else if str.hasPrefix("A4") {
                let start = str.index(str.startIndex, offsetBy: 4)
                let end = str.index(str.endIndex, offsetBy: -4)
                let newStr = str[start..<end]
                debugPrint("蓝牙外设收到指令：" + str)
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_DEVICE_DATA_A4"), object: newStr)
            } else if str.hasPrefix("B4") || str.hasPrefix("B5") {
                if str.count > 10 {
                    let start = str.index(str.startIndex, offsetBy: 4)
                    let end = str.index(str.startIndex, offsetBy: 12)
                    let newStr = str[start..<end]
                    let num = Int.init(newStr)
                    let start2 = str.index(str.startIndex, offsetBy: num == 0 ? 16 : 12)
                    let end2 = str.index(str.endIndex, offsetBy: -4)
                    let newStr2 = str[start2..<end2]
                    let endStr = str[str.index(str.endIndex, offsetBy: -2)..<str.endIndex]
                    if str.hasPrefix("B4") {
                        debugPrint("蓝牙外设收到指令：" + str)
                        if endStr == "00" {
                            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_DEVICE_DATA_B4_END"), object: String(newStr2))
                        } else {
                            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_DEVICE_DATA_B4"), object: String(newStr2))
                        }
                    } else if str.hasPrefix("B5") {
                        debugPrint("蓝牙外设收到指令：" + str)
                        if endStr == "00" {
                            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_DEVICE_DATA_B5_END"), object: String(newStr2))
                        } else {
                            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_DEVICE_DATA_B5"), object: String(newStr2))
                        }
                    }
                }
            } else if str.hasPrefix("B6") {
                if str.count > 10 {
                    let start = str.index(str.startIndex, offsetBy: 12)
                    let end = str.index(str.endIndex, offsetBy: -4)
                    let newStr = str[start..<end]
                    let endStr = str[str.index(str.endIndex, offsetBy: -2)..<str.endIndex]
                    if endStr == "00" {
                        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_DEVICE_DATA_B6_END"), object: String(newStr))
                    } else {
                        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "GET_DEVICE_DATA_B6"), object: String(newStr))
                    }
                    debugPrint(str)
                }
            } else if str.count <= 10 {
                debugPrint("蓝牙外设收到指令：" + str)
            } else {
                debugPrint("蓝牙外设收到异常指令：" + str)
            }
        } else if characteristic.uuid.uuidString == "8EC90003-F315-4F60-9FB8-838830DAEA50" {
            debugPrint("设备返回到的数据 \(characteristic.uuid.uuidString): \(characteristic.value!.hexString())")
        }
    }
    
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        if error == nil {
            debugPrint("数据写入成功")
        } else {
            debugPrint("数据写入失败")
        }
    }
    
}

extension String {
    ///16进制字符串转Data
    func hexData() -> Data? {
        var data = Data(capacity: count / 2)
        let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
        regex.enumerateMatches(in: self, range: NSMakeRange(0, utf16.count)) { match, flags, stop in
            let byteString = (self as NSString).substring(with: match!.range)
            var num = UInt8(byteString, radix: 16)!
            data.append(&num, count: 1)
        }
        guard data.count > 0 else { return nil }
        return data
    }
    
    func utf8Data()-> Data? {
        return self.data(using: .utf8)
    }
    
}

extension Data {
    ///Data转16进制字符串
    func hexString() -> String {
        return map { String(format: "%02x", $0) }.joined(separator: "").uppercased()
    }
}
